home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SPACE 2
/
SPACE - Library 2 - Volume 1.iso
/
apps
/
42
/
wind7.prf
< prev
next >
Wrap
Text File
|
1986-07-17
|
18KB
|
406 lines
.!****************************************************************************
.!
.! ANTIC PUBLISHING INC., COPYRIGHT 1985. REPRINTED BY PERMISSION.
.!
.! ** Professional GEM ** by Tim Oren
.!
.! Proff File by ST enthusiasts at
.! Case Western Reserve University
.! Cleveland, Ohio
.! uucp : decvax!cwruecmp!bammi
.! csnet: bammi@case
.! arpa : bammi%case@csnet-relay
.! compuserve: 71515,155
.!
.!****************************************************************************
.!
.!
.!****************************************************************************
.!
.! Begin Part 7
.!
.!****************************************************************************
.!
.PART VII Menu Structures
.SH HAPPY NEW YEAR
This is article number seven in the ST
PRO GEM series, and the first for 1986. In this installment,
I will be discussing GEM menu structures and how to use them
in your application. There is also a short Feedback
response section. You will find the download file containing
the code for this column in the file GEMCL7.C in DL3 of the
ATARI16 SIG (PCS-58).
.SH MENU BASICS
In ST GEM, the menu consists of a bar
across the top of the screen which displays several sub-menu
titles. Touching one of the titles causes it to highlight,
and an associated "drop-down" to be drawn directly below on
the screen. This drop-down may be dismissed by moving to
another title, or by clicking the mouse off of the drop-down.
.PP
To make a selection, the mouse is moved over the
drop-down. Each valid selection is highlighted when the
mouse touches it. Clicking the mouse while over one of
these selections picks that item. GEM then undraws the
drop-down, and sends a message to your application giving the
object number of the title bar entry, and the object number
of the drop-down item which were selected by the user. The
selected title entry is left highlighted while your code
processes the request.
.SH MENU STRUCTURES
The data structure which defines a GEM
menu is (surprise!) an object tree, just like the dialogs and
panels which we have discussed before. However, the
operations of the GEM menu manager are quite different from
those of the form manager, so the internal design of the menu
tree has some curious constraints.
.PP
The best way to understand these constraints is to look
at an example. The first item in the download is the object
structure (only) of the menu tree from the GEM Doodle/Demo
sample application.
.PP
The ROOT of a menu tree is sized to fit the entire
screen. To satisfy the visual hierarchy principle (see
article #5), the screen is divided into two parts: THE BAR,
containing the menu titles, and THE SCREEN, while contains
the drop-downs when they are drawn. Each of these areas is
defined by an object of the same name, which are the only two
objects linked directly below the ROOT of a menu tree. You
will notice an important implication of this structure: The
menu titles and their associated drop-downs are stored in
entirely different subtrees of the menu!
.PP
While examining THE BAR in the example listing, you may
notice that its OB_HEIGHT is very large (513). In
hexadecimal this is 0x0201. This defines a height for THE
BAR of one character plus two pixels used for spacing. THE
BAR and its subtree are the only objects which are drawn on
the screen in the menu's quiescent state.
.PP
The only offspring object of THE BAR is THE ACTIVE. This
object defines the part of THE BAR which is covered by menu
titles. The screen rectangle belonging to THE ACTIVE is used
by the GEM screen manager when it waits for the mouse to
enter an active menu title. Notice that THE ACTIVE and its
offspring also have OB_HEIGHTs with pixel residues.
.PP
The actual menu titles are linked left to right in order
below THE ACTIVE. Their OB_Xs and OB_WIDTHs are arranged so
that they completely cover THE ACTIVE. Normally, the title
objects are typed G_TITLE, a special type which assures that
the title bar margins are correctly drawn.
.PP
THE SCREEN is the parent object of the drop-down boxes
themselves. They are linked left to right in an order
identical with their titles, so that the menu manager can
make the correct correspondence at run-time. The OB_X of
each drop-down is set so that it is positioned below its
title on the screen.
.PP
Notice that it is safe to overlap the drop-downs within a
menu, since only one of them will be displayed at any time.
There is one constraint on the boxes however: They must be
no greater than a quarter screen in total size. This is the
size of the off-screen blit buffer which is used by GEM to
store the screen contents when the drop-down is drawn. If
you exceed this size, not all the screen under the drop-down
will be restored, or the ST may crash!
.PP
The entries within a drop-down are usually G_STRINGs,
which are optimized for drawing speed. The rectangles of
these entries must completely cover the drop-down, or the
entire drop-down will be inverted when the mouse touches an
uncovered area! Techniques for using objects other than
G_STRINGs are discussed later in this column.
.PP
The first title and its corresponding drop-down are
special. The title name, by custom, is set to DESK. The
drop-down must contain exactly eight G_STRING objects. The
first (again by custom) is the INFO entry, which usually
leads to a dialog displaying author and copyright information
for your application. The next is a separator string of
dashes with the DISABLED flag set. The following six objects
are dummy strings which GEM fills in with the names of desk
accessories when your menu is loaded.
.PP
The purpose of this description of menu trees is to give
you an understanding of what lies "behind the scenes" in the
next section, which describes the run-time menu library
calls. In practice, the Resource Construction Set provides
"blank menus" which include all of the required elements, and
it also enforces the constraints on internal structure. You
only need to worry about these if you modify the menu tree
"on-the-fly".
.SH USING THE MENU
once you have loaded the application's
resource, you can ask the AES to install your menu. You must
first get the address of the menu tree within the resource
using:
.FB rsrc_gaddr()
rsrc_gaddr(R_TREE, MENUTREE, &ad_menu);
.FE
assuming that MENUTREE is the name you gave the menu in the
RCS, and that ad_menu is a LONG which will receive the
address. Then you call the AES to establish the menu:
.FB menu_bar()
menu_bar(ad_menu, TRUE);
.FE
At this point, the AES draws your menu bar on the screen and
animates it when the user moves the mouse into the title
area.
.PP
The AES indicates that the user has made a menu selection
by sending your application a message. The message type is
MN_SELECTED, which will be stored in msg[0], the first
location in the message returned by evnt_multi().
.PP
The AES also stores the object number of the selected
menu's title in msg[3], and the object number of the
selected menu item in msg[4]. Generally, your application
will process menu messages with nested C switch statements.
The outer switch will have one case for each menu title, and
the inner switch statements will have a case for each entry
within the selected menu. (This implies that you must give a
name to each title and to each menu entry when you create the
menu in the RCS.)
.PP
After the user has made a menu selection, the AES leaves
the title of the chosen menu in reverse video to indicate
that your application is busy processing the message. When
you done with whatever action is indicated, you need to
return the title to a normal state. This is done with
.FB menu_tnormal()
menu_tnormal(ad_menu, msg[3], TRUE);
.FE
.sp 1
.ce 1
(Remember that msg[3] is the title's object number.)
.sp 1
When your application is ready to terminate, it should
delete its menu bar. Do this with the call:
menu_bar(ad_menu, FALSE);
.SH GETTING FANCY
The techniques above represent the bare
minimum to handle menus. In most cases, however, you will
want your menus to be more "intelligent" in displaying the
user's options. For instance, you can prevent many user
errors by disabling inappropriate choices, or you can save
space on drop-downs by showing only one line for a toggle and
altering its text or placing and removing a check mark when
the state is changed. This section discusses these and other
advanced techniques.
.PP
It is a truism of user interface design that the best way
to deal with an error is not to let it happen in the first
place. It many cases, you can apply this principle to GEM
menus by disabling choices which should not be used. If
your application uses a "selection precedes action" type of
interface, the type of object selected may give the
information needed to do this. Alternately, the state of
the underlying program may render certain menu choices
illegal.
.PP
GEM provides a call to disable and re-enable menu
options. The call is:
.FB menu_ienable()
menu_ienable(ad_menu, ENTRY, FALSE);
.FE
to disable a selection. The entry will be grayed out when
it is drawn, and will not invert under the mouse and will not
be selected by the user. Substituting TRUE for FALSE
re-enables the option. ENTRY is the name of the object
which is being affected, as assigned in the RCS.
.PP
Note that menu_ienable() will not normally affect the
appearance or operation of menu TITLE entries. However,
there is an undocumented feature which allows this. If ENTRY
is replaced by the object number of a title bar entry with
its top bit set, then the entire associated drop-down will be
disabled or re-enabled as requested, and the title's
appearance will be changed. But, be warned that this feature
did not work reliably in some early versions of GEM. Test it
on your copy of ST GEM, and use it with caution when you
cannot control the version under which your application may
run.
.PP
It is also possible to disable menu entries by directly
altering the DISABLED attribute within the OB_STATE word.
The routines enab_obj() and disab_obj() in the download show
how this is done. They are also used in set_menu(), which
follows them immediately.
.PP
Set_menu() is a utility which is useful when you wish to
simultaneously enable or disable many entries in the menu
when the program's state changes or a new object is selected
by the user. It is called with
.FB set_menu()
set_menu(ad_menu, vector);
.FE
where vector is a pointer to an array of WORDs. The first
word of the array determines the default state of menu
entries. If it is TRUE, then set_menu() enables all entries
in every drop-down of the menu tree, except that the DESK
drop-down is unaffected. If it is FALSE, then every menu
entry is disabled.
.PP
The following entries in the array are the numbers of
menu entries which are to be toggled to the reverse of the
default state. This list is terminated by a zero entry.
.PP
The advantage of set_menu() is that it allows you to
build a collection of menu state arrays, and associate one
with each type of user-selected object, program state, and so
on. Changing the status of the menu tree may then be
accomplished with a single call.
.SH CHECK, PLEASE?
One type of state indicator which may
appear within a drop-down is a checkmark next to an entry.
You can add the checkmark with the call:
.FB menu_icheck()
menu_icheck(ad_menu, ENTRY, TRUE);
.FE
and remove it by replacing the TRUE with FALSE. As above,
ENTRY is the name of the menu entry of interest. The
checkmark appears inside the left boundary of the entry
object, so leave some space for it.
.PP
The menu_icheck() call is actually changing the state of
the CHECKED flag within the entry object's OB_STATE word. If
necessary, you may alter the flag directly using do_obj() and
undo_obj() from the download.
.SH NOW YOU SEE IT, NOW YOU DON'T
You can also alter the
text which appears in a particular menu entry (assuming that
the entry is a G_STRING object). The call
.FB menu_text()
menu_text(ad_menu, ENTRY, ADDR(text));
.FE
will substitute the null-terminated string pointed to by
text for whatever is currently in ENTRY. Remember to make
the drop-down wide enough to handle the largest text string
which you may substitute. In the interests of speed,
G_STRINGs drawn within drop-downs are not clipped, so you may
get garbage characters on the desktop if you do not size the
drop-down properly!
.PP
The menu_text() call actually alters the OB_SPEC field of
the menu entry object to point to the string which you
specify. Since the menu tree is a static data structure
which may be directly accessed by the AES at any time, be
sure that the string is also statically allocated and that it
is not modified without first being delinked from the menu
tree. Failure to do this may result in random crashes when
the user accesses the drop-down!
.SH LUNCH AND DINNER MENUS
Some applications may have such
a wide range of operations that they need more than one menu
bar at different times. There is no problem with having
more than one menu tree in a resource, but the AES can only
keep track of one at a time. Therefore, to switch menus you
need to use menu_bar(ad_menu1, FALSE); to release the first
menu, then use menu_bar(ad_menu2, TRUE); to load the second
menu tree.
.PP
Changing the entire menu is a drastic action. Out of
consideration for your user, it should be associated with
some equally obvious change in the application which has just
been manually requested. An example might be changing from
spreadsheet to data graphing mode in a multi-function
program.
.SH DO IT YOURSELF
In a future column, I will discuss how
to set up user-defined drawing objects. If you have already
discovered them on your own, you can use them within a
drop-down or as a title entry.
.PP
If the user-defined object is within a drop-down, its
associated drawing code will be called once when the
drop-down is first drawn. It will then be called in
"state-change" mode when the entry is highlighted (inverted).
This allows you to use non-standard methods to show
selection, such as outlines.
.PP
If you try to insert a user-defined object within the
menu title area, remember that the G_TITLE object which you
are replacing includes part of the dark margin of the bar.
You will need to experiment with your object drawing code to
replicate this effect.
.SH MAKE PRETTY
There are a number of menu formatting
conventions which have become standard practice. Using these
gives your application a recognizable "look-and-feel" and
helps users learn it. The following section reviews these
conventions, and supplies a few hints and tricks to obtain a
better appearance for you menus.
.PP
The second drop-down is customarily used as the FILE
menu. It contains options related to loading and saving the
files used by the application, as well as entries for
clearing the workspace and terminating the program.
.PP
You should avoid crowding the menu bar. Leave a couple
of spaces between each entry, and try not to use more than
70% of the bar. Not only does this look better, but you will
have space for longer words if you translate your application
to a foreign language.
.PP
Similarly, avoid cluttering menu drop-downs. Try to keep
the number of options to no more than ten unless they are
clearly related, such as colors. Separate off dissimilar
entries with the standard disabled dashes line. (If you are
using set_menu(), remember to consider the separators when
setting up the state vectors.)
.PP
If the number of options grows beyond this bound, it may
be time to move them to a dialog box. If so, it is a
convention to put three dots following each menu entry which
leads to a dialog. Also, allow a margin on the menu entries.
Two leading blanks and a minimum of one trailing blank is
standard, and allows room for checkmarks if they are used.
.PP
Dangerous menu options should be far away from common
used entries, and are best separated with dashed lines. Such
options should either lead to a confirming go/no-go alert, or
should have associated "undo" options.
.PP
After you have finished defining a menu drop-down with
the RCS, be sure that its entries cover the entire box.
Then use ctrl-click to select the drop-down itself, and SORT
the entries top to bottom. This way the drop-down draws in
smoothly top to bottom.
.PP
Finally, it is possible to put entries other than
G_STRINGs into drop-downs. In the RCS, you will need to
import them via the clipboard from the Dialog mode.
.PP
Some non-string object, such as icons and images, will
look odd when they are inverted under the mouse. There is a
standard trick for dealing with this problem. Insert the
icon or whatever in the drop-down first. Then get a G_IBOX
object and position and size it so that it covers the first
object as well as the extra area you would like to be
inverted.
.PP
Edit the G_IBOX to remove its border, and assign the
entry name to it. Since the menu manager uses objc_find(),
it will detect and invert this second object when the mouse
moves into the drop-down. (To see why, refer to article #5.)
Finally, DO NOT SORT a drop-down which has been set up this
way!
.SH THAT'S IT FOR NOW!
The next column will discuss some of
the principles of designing GEM interfaces for applications.
This topic is irreverantly known as GEM mythology or
interface religion. The subject for the following column is
undecided. I am considering mouse and keyboard messages, VDI
drawing primitives, and the file selector as topics. Let me
know your preferences in the Feedback!
.!
.!
.!*****************************************************************************
.!* *
.!* End Part 7 *
.!* *
.!*****************************************************************************